import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.Random;


public class Tank {
	public static final int GX_SPEED =10;
	public static final int GY_SPEED =10;
	public static final int BX_SPEED =5;
	public static final int BY_SPEED =5;
	
	public static final int WIDTH = 30;
	public static final int HEIGHT = 30;
	public static  int X_SPEED =1;
	public static  int Y_SPEED =1;
	
	public static Random random = new Random();
	
	protected  TankClient tc = null;
	public  enum Direction {UP,R_UP,RIGHT,R_DOWN,DOWN,L_DOWN,LEFT,L_UP,STOP};
	
	private BloodBar bb = new BloodBar();
	private int oldX;
	private int oldY;
	
	private Direction dir = Direction.STOP; 
	private Direction ptDir = Direction.DOWN; 
	
	private boolean good = false;
	private boolean live = true;
	
	private int life = 100;
	
	public int getLife() {
		return life;
	}

	public void setLife(int life) {
		this.life = life;
	}

	public boolean isGood() {
		return good;
	}

	private boolean bup =false,bright = false,bdown = false,bleft = false;
	private int step = random.nextInt(12) + 3;
	private int x,y;
	
	
	public Tank(int x, int y ,boolean good) {
		oldX = x;
		oldY = y;
		this.x = x;
		this.y = y;
		this.good = good;
	}
	
	public Tank(int x,int y ,boolean good ,Tank.Direction dir,TankClient tc)
	{
		
		this(x,y,good);
		this.dir = dir;
		this.tc = tc;
		if (good) {
			X_SPEED = GX_SPEED;	
			Y_SPEED = GY_SPEED;
			}else {
				X_SPEED = BX_SPEED;
				Y_SPEED = BY_SPEED;
			}
	}
	public void draw(Graphics g)
	{
		if (!live) {
			if (!good) {
				tc.tanks.remove(this);
			}
			return ;
		}
		
		if (isGood()) {
			bb.draw(g);
		}
		
		Color c = g.getColor();
		if (good) {
			g.setColor(Color.BLUE);
		}else {
			g.setColor(Color.RED);
		}
		
		g.fillOval(x, y, WIDTH, HEIGHT);
		g.setColor(c);
		move();
		switch (ptDir) {
		case UP:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x +Tank.WIDTH/2 , y);
			break;
		case R_UP:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH  , y);
			break;
		case RIGHT:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x +Tank.WIDTH , y + Tank.HEIGHT/2);
			break;
		case R_DOWN:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x +Tank.WIDTH , y + Tank.HEIGHT);
			break;
		case DOWN:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x +Tank.WIDTH/2 , y + Tank.HEIGHT);
			break;
		case L_DOWN:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x  , y + Tank.HEIGHT);
			break;
		case LEFT:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x  , y + Tank.HEIGHT/2);
			break;
		case L_UP:
			g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x  , y);
			break;
		
		}
	}
	
	public boolean isLive() {
		return live;
	}

	public void setLive(boolean live) {
		this.live = live;
	}

	public void keyPressed(KeyEvent g) {
		int keyCode = g.getKeyCode();
		switch (keyCode) {
		case KeyEvent.VK_UP:
			bup = true;
			break;
		case KeyEvent.VK_DOWN:
			bdown = true;
			break;
		case KeyEvent.VK_LEFT:
			bleft = true;
			break;
		case KeyEvent.VK_RIGHT:
			bright = true;
			break;
		case KeyEvent.VK_F2:
			if (!this.live) {
				this.live =  true;
				this.life = 100;
			}
			break;
		default:
			break;
		}
		direction();
	}
	public void keyReleased(KeyEvent g) {
		int keyCode = g.getKeyCode();
		switch (keyCode) {
		case KeyEvent.VK_CONTROL:
			fire();
			break;
		case KeyEvent.VK_UP:
			bup = false;
			break;
		case KeyEvent.VK_DOWN:
			bdown = false;
			break;
		case KeyEvent.VK_LEFT:
			bleft = false;
			break;
		case KeyEvent.VK_RIGHT:
			bright = false;
			break;
		case KeyEvent.VK_A:
			superFire();
			break;
		default:
			break;
		}
		direction();
	}
	
	public void direction()
	{
		if (bup == true && bright != true && bdown != true && bleft != true) {
			dir = Direction.UP;
		} else if (bup == true && bright == true && bdown != true
				&& bleft != true) {
			dir = Direction.R_UP;
		} else if (bup != true && bright == true && bdown != true
				&& bleft != true) {
			dir = Direction.RIGHT;
		} else if (bup != true && bright == true && bdown == true
				&& bleft != true) {
			dir = Direction.R_DOWN;
		} else if (bup != true && bright != true && bdown == true
				&& bleft != true) {
			dir = Direction.DOWN;
		} else if (bup != true && bright != true && bdown == true
				&& bleft == true) {
			dir = Direction.L_DOWN;
		} else if (bup != true && bright != true && bdown != true
				&& bleft == true) {
			dir = Direction.LEFT;
		} else if (bup == true && bright != true && bdown != true
				&& bleft == true) {
			dir = Direction.L_UP;
		}
		else if (bup != true && bright != true && bdown != true
				&& bleft != true) {
			dir = Direction.STOP;
		}

	}

	public void move() {
		
		this.oldX = x;
		this.oldY = y;
		
		switch (dir) {
		case UP:
			y -= Y_SPEED;
			break;
		case R_UP:
			x += X_SPEED;
			y -= Y_SPEED;
			break;
		case RIGHT:
			x += X_SPEED;
			break;
		case R_DOWN:
			x += X_SPEED;
			y += Y_SPEED;
			break;
		case DOWN:
			y += Y_SPEED;
			break;
		case L_DOWN:
			x -= X_SPEED;
			y += Y_SPEED;
			break;
		case LEFT:
			x -= X_SPEED;
			break;
		case L_UP:
			x -= X_SPEED;
			y -= Y_SPEED;
			break;
		case STOP:
			break;
		}
		if (this.dir != Direction.STOP) {
			this.ptDir  = this.dir;
		}
		
		if (x < 0) { x = 0;}
		if (y < 25) { y = 25 ;}
		if (x + Tank.WIDTH > TankClient.GAME_WIDTH) { x = TankClient.GAME_WIDTH - Tank.WIDTH;}
		if (y + Tank.HEIGHT > TankClient.GAME_HEIGHT) { y = TankClient.GAME_HEIGHT -Tank.HEIGHT;}
		
		if (!good) {
			Direction[] dirs = Direction.values();
			if (step == 0) {
				step = random.nextInt(12)+3;
				int rn = random.nextInt(dirs.length);
			/*	while (rn == 8 ) {
					rn = random.nextInt(dirs.length);
				}*/
				dir = dirs[rn];
		}
		step--;
		if (random.nextInt(40) > 38) {
			fire();
		}
		
		}
}

	private Missile fire()
	{	if (!isLive()) 
			return null;
		int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2;
	    int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;
	    
		Missile m = new Missile(x, y,good, ptDir,tc);
		tc.missiles.add(m);
		return m;
 	}
	
	private Missile fire(Direction dir) {
		if (!isLive()) 
			return null;
		int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2;
	    int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;
	    
		Missile m = new Missile(x, y,good,dir,tc);
		tc.missiles.add(m);
		return m;
	}
	
	public Rectangle getRec()
	{
		return new Rectangle(x,y,WIDTH,HEIGHT);
	}
	
	public boolean collidesWithWall (Wall w) {
		if (this.live&&this.getRec().intersects(w.getRec())) {
			this.stay();
			return true;
		}
		return false;
		
	}

	public boolean colledesWithTanks(List<Tank> tanks) {
		for (int i = 0; i < tanks.size(); i++) {
			Tank t = tanks.get(i);
			if (this != t) {
				if (this.live && t.isLive() &&this.getRec().intersects(t.getRec())) {
					this.stay();
					t.stay();
					return true;
				}
			}
		}
		
		return false;
	}
	public boolean eat(Blood b)
	{
		if (this.live&&b.isLive()&&this.getRec().intersects(b.getRec())) {
			this.setLife(100);
			b.setLive(false);
			return true;
		}
		return false;
			
	}
	
	private void stay() {
		this.x = oldX;
		this.y = oldY;
		
	}
	
	
	private void superFire()
	{
		Direction[] dirs = Direction.values();
		for (int i = 0; i < 8; i++) {
			fire(dirs[i]);
		}
	}
	
	
	private class BloodBar{
		public void draw(Graphics g)
		{
			Color c = g.getColor();
			g.setColor(Color.RED);
			g.drawRect(x, y - 10, WIDTH, 10);
			int w = WIDTH*life/100; 
			g.fillRect(x, y - 10, w, 10);
			g.setColor(c);
		}
	}
}
